/**
  ******************************************************************************
  * @author     Chris
  * @since      2024/6/18 16:18
  *
  * @file       pd_exti.c
  * @brief      Xxx hardware driver.
  *
  * @note       This file contains the hardware driver for the OLED.
  *
  * @warning    None.
  ******************************************************************************
  * Change Logs:
  *   Date          Author       Notes
  *   2024/6/18     Chris        the first version
  *
  ******************************************************************************
  */


#include <pd_exti.h>
#include <stm32f4xx_ll_exti.h>
#include <stm32f4xx_ll_system.h>
#include <stm32f4xx_ll_gpio.h>
#include <stm32f4xx_ll_bus.h>

static void ExternalTI_init(ExtIR *this, IRQn_Type irQnType, uint32_t PreemptPriority, uint32_t SubPriority) {
    this->gpio->init(this->gpio);

    LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SYSCFG);

    LL_SYSCFG_SetEXTISource(this->Port, this->Line);

    LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
    EXTI_InitStruct.Line_0_31   = this->Line_0_31;
    EXTI_InitStruct.LineCommand = this->LineCommand;
    EXTI_InitStruct.Mode        = this->Mode;
    EXTI_InitStruct.Trigger     = this->Trigger;
    LL_EXTI_Init(&EXTI_InitStruct);

    // NVIC also can be init in main.c
    NVIC_SetPriority(irQnType, NVIC_EncodePriority(
            NVIC_GetPriorityGrouping(), PreemptPriority, SubPriority));
    NVIC_EnableIRQ(irQnType);
}

static ExtIR *build(GPIO *gpio, uint32_t Line_0_31, uint32_t Port, uint32_t Line) {
    ExtIR *extIR = malloc(sizeof(ExtIR));

    Driver_add(extIR, GEN_PERM);

    gpio->Mode = LL_GPIO_MODE_INPUT;

    extIR->gpio        = gpio;
    extIR->Port        = Port;
    extIR->Line        = Line;
    extIR->Line_0_31   = Line_0_31;
    extIR->LineCommand = ENABLE;
    extIR->Mode        = LL_EXTI_MODE_IT;
    extIR->Trigger     = LL_EXTI_TRIGGER_RISING;
    extIR->init        = &ExternalTI_init;

    return extIR;
}

const struct ExtIRClass ExtIRBuilder = {.build = &build};
